package com.smzd.framework.system.business;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.smzd.core.dao.IDao;
import com.smzd.framework.core.business.AbstractFGService;
import com.smzd.framework.exceptions.UsernameAlreadyExistsException;
import com.smzd.framework.security.domain.Authority;
import com.smzd.framework.system.dao.MeetingDao;
import com.smzd.framework.system.dao.RoleDao;
import com.smzd.framework.system.dao.UserDao;
import com.smzd.framework.system.domain.Meeting;
import com.smzd.framework.system.domain.Role;
import com.smzd.framework.system.domain.User;
import com.smzd.framework.utils.CharSetConverter;
import com.smzd.framework.utils.Privilege;
import com.smzd.framework.utils.db.FGRowConverter;
import com.smzd.framework.utils.db.ORPage;
import com.smzd.framework.utils.db.RPage;
import com.smzd.utils.E;
import com.smzd.utils.FileUtil;

@Service
public class UserService extends AbstractFGService<User> implements UserDetailsService{
	public static final String DIR_HEADERS = "images/headers";
	@Autowired
	private UserDao dao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private MeetingDao meetingDao;
	@Autowired(required=false)
	@Qualifier("charsetConverter")
	private CharSetConverter charsetConverter;
	
	@Override
	protected IDao<User> getDao() {
		return dao;
	}

	@Override
	public FGRowConverter<User> getConverter() {
		return UserService.converter;
	}

	private static FGRowConverter<User> converter = new FGRowConverter<User>() {
		@Override
		public Object[] convert(User elem) {
			String ownerName = elem.getOwner() == null ? null : elem.getOwner()
					.getName();
			Object[] fields = new Object[] { 
					elem.getId(), 
					elem.getName(),
					elem.getGender(),
					elem.getType(),
					elem.getDescription(),
					ownerName,
					elem.getEmail(),
					elem.getMobile(),
					elem.getAvatar()
			};
			return fields;
		}
	};

	public User getUserByUserName(String name) {
		return dao.getUserByName(name);
	}
	/**
	 * 获取所有的角色作为权限。
	 * @return
	 */
	public Privilege getPrivilegeForUser0(){
	    List<Role> roles = roleDao.getRolesInAllModules();
	    Privilege privilege = new Privilege();
	    privilege.setRoles(roles);
	    return privilege;
	}
	/**
	 * 获取用户进入所属Meeting的权限。用户是普通用户，只需要通过用户组授权即可获得全部权限
	 * @param user
	 * @return
	 */
	public Privilege getPrivilegeForUser(User user){
        if(user.getOwner()==null){
            throw new RuntimeException("user.owner为空，无法获得其权限！");
        }
        Meeting meeting = user.getOwner();
        if(meeting.getOwner()==null){
            meeting = meetingDao.getElemById(meeting.getId());
            user.setOwner(meeting);
        }
	    if(user.getOwner().getOwner().getId().intValue()==user.getId().intValue()){
	        return getPrivilegeForUser0();
	    }
        List<Role> userRoles = roleDao.getPrivilegeRolesByUserId(user.getId());
        List<Role> roles = new ArrayList<>();
        if(userRoles!=null&&userRoles.size()>0){
            roles.addAll(userRoles);
        }
        Privilege privilege = new Privilege();
        privilege.setRoles(roles);
        return privilege;
	}
	
	/**
	 * 获取Meeting的Owner所拥有的权限。<br>
	 * Meeting的Owner的权限分为两部分，
	 * 一部分是当前Meeting所配备的模块中所包含的所有权限，
	 * 另一部分是Meeting的Owner在其所属的Meeting中所赋予的权限。
	 * @param meeting
	 * @return
	 */
    public Privilege getPrivilegeForOwner(Meeting meeting) {
        if(meeting.getOwner()==null){
            throw new RuntimeException("meeting.owner为空，无法获得其owner的权限！");
        }
        User user = meeting.getOwner();
        if(user.getOwner()==null){
            user = dao.getElemById(user.getId());
            meeting.setOwner(user);
        }
        if (user.getOwner().getId().intValue() == meeting.getId()) {
            return getPrivilegeForUser0();
        }
        List<Role> meetingRoles = roleDao.getPrivilegeRolesByMeetingId(meeting.getId());
        List<Role> userRoles = roleDao.getPrivilegeRolesByUserId(meeting.getOwner().getId());
        List<Role> roles = new ArrayList<>();
        if (meetingRoles != null && meetingRoles.size() > 0) {
            roles.addAll(meetingRoles);
        }
        if (userRoles != null && userRoles.size() > 0) {
            roles.addAll(userRoles);
        }
        Privilege privilege = new Privilege();
        privilege.setRoles(roles);
        return privilege;

    }

	public String getOwnersListInJson(int meetingId) {
		RPage<User> page = new RPage<User>();
		List<User> owners = dao.getAllOwners(meetingId);
		page.setElems(owners);
		page.setTotalCount(owners.size());
		return page.toFlexiGridJsonString(converter);
	}

	private final static List<GrantedAuthority> authorities = Arrays
			.asList((GrantedAuthority) new Authority("ROLE_USER"));
	
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
	    if(charsetConverter!=null){
	        username = charsetConverter.convert(username);
	    }
		User user = getUserByUserName(username);
		if(user!=null){
			user.setAuthorities(authorities);
		}
		return user;
	}
	
	public void updatePassword(User user){
		dao.updatePassword(user);
	}

    public User register(User user) throws UsernameAlreadyExistsException {
        return register(user, null);
    }

	public User register(User user, MultipartFile avatar_file) throws UsernameAlreadyExistsException {
		if(avatar_file!=null){
			String avatar = null;
			try {
				avatar = uploadUserHead(avatar_file);
			} catch (Exception e) {
				e.printStackTrace();
			}
			user.setAvatar(avatar);
		}
		User user1 = getUserByUserName(user.getName());
        if (user1 != null) {
            throw new UsernameAlreadyExistsException(user.getName());
        }
        user.setId(null);
		if(StringUtils.isEmpty(user.getPassword())){
			user.setPassword("123456");
		}
		dao.insert(user);
		return user;
	}

	private String uploadUserHead(MultipartFile avatar_file) throws Exception {
        String origin = avatar_file.getOriginalFilename();
        int idx = origin.lastIndexOf(".");
        if (idx < 0) {
            E.throwRE("文件格式不正确！");
        }
        String ext = origin.substring(idx);
    	String uuid = UUID.randomUUID().toString() + ext;
    	File app_root = FileUtil.getAppRoot();
    	File dir_headers = new File(app_root, DIR_HEADERS);
    	dir_headers.mkdirs();
        File diskfile = new File(dir_headers, uuid);
        avatar_file.transferTo(diskfile);
		return uuid;
	}

	public String getUsersWithGroups(int[] gids, Meeting meeting) {
		ORPage<Meeting, User> page = new ORPage<Meeting, User>(); 
		if(gids==null||gids.length==0){
			page.setElems(new ArrayList<User>());
		}else{
			page.setPageSize(999);
			page.setOwner(meeting);
	        StringBuffer sb = new StringBuffer();
	        for(int i=0; i<gids.length; i++){
	            int a = gids[i];
	            sb.append(a);
	            if(i<gids.length-1){
	                sb.append(",");
	            }
	        }
			page.setQuery(sb.toString());
			dao.getUsersWithGroups(page);
		}
		return page.toFlexiGridJsonString(converter);
	}

}
